﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

using System.Diagnostics;
using System.Net;
using System.Web;
using SimpleJson;

namespace FacebookTestUserManager
{
    public class FacebookHelper
    {
        public const string AccessTokenUrl = "https://graph.facebook.com/oauth/access_token?client_id={0}&client_secret={1}&grant_type=client_credentials";
        public const string TestUserUrl = "https://graph.facebook.com/{0}/accounts/test-users?{1}";
        public const string AppsUrl = "https://graph.facebook.com/{0}?{1}";
        public const string CreateUrl = "https://graph.facebook.com/{0}/accounts/test-users";
        public const string DeleteUrl = "https://graph.facebook.com/{0}";
        public const string FriendsUrl = "https://graph.facebook.com/{0}/friends/{1}";


        public string AppId { get; set; }
        public string AccessToken { get; set; }

        public FacebookHelper(string appId, string accessToken)
        {
            this.AppId = appId;
            this.AccessToken = accessToken;
        }

        public static string GetAccessToken(string appId, string appSecret)
        {
            var address = string.Format(AccessTokenUrl, appId, appSecret);

            var client = new WebClient();
            var data = client.DownloadString(address);

            return data;
        }

        public static void NavigateTo(string url)
        {
            var browserPath = Config.Get("BrowserPath");

            if (string.IsNullOrWhiteSpace(browserPath))
            {
                Process.Start(url); //for default browser
            }
            else
            {
                Process.Start(browserPath, url);
            }
        }


        public dynamic GetAppsInformation()
        {
            var address = string.Format(AppsUrl, this.AppId, this.AccessToken);

            var client = new WebClient();
            var data = client.DownloadString(address);
            
            dynamic result = SimpleJson.SimpleJson.DeserializeObject(data);

            return result;

        }

        public List<TestUser> GetTestUsers()
        {
            var address = string.Format(TestUserUrl, this.AppId, this.AccessToken);

            var client = new WebClient();
            var response = client.DownloadString(address);
            dynamic result = SimpleJson.SimpleJson.DeserializeObject(response);

            var users = new List<TestUser>();
            foreach (var user in result["data"])
                users.Add(SimpleJson.SimpleJson.DeserializeObject<TestUser>(user.ToString()));


            return users;

        }

        public TestUser CreateTestUser(bool installed, List<UserPermissions> userPermissions, List<FriendPermissions> friendPermissions)
        {

            var permissions = new List<string>();

            if (userPermissions != null)
            {
                foreach (var p in userPermissions)
                {
                    permissions.Add(Enum.GetName(typeof(UserPermissions), p));
                }
            }

            if (friendPermissions != null)
            {
                foreach (var p in friendPermissions)
                {
                    permissions.Add(Enum.GetName(typeof(FriendPermissions), p));
                }
            }

            var address = string.Format(CreateUrl, this.AppId);
            var param = string.Format("installed={0}&permissions={1}&{2}",
                installed.ToString().ToLower(),
                string.Join(",", permissions.ToArray()),
                this.AccessToken
                );


            var client = new WebClient();
            client.Encoding = Encoding.UTF8;
            client.Headers["content-type"] = "application/x-www-form-urlencoded";

            var response = client.UploadString(address, param);

            return SimpleJson.SimpleJson.DeserializeObject<TestUser>(response);

        }

        public bool DeleteTestUser(string id)
        {
            var address = string.Format(DeleteUrl, id);
            var param = this.AccessToken;

            var client = new WebClient();
            client.Encoding = Encoding.UTF8;
            client.Headers["content-type"] = "application/x-www-form-urlencoded";

            var response = client.UploadString(address, "DELETE", param);

            return response == "true";
        }

        public bool Friends(string userId, string friendId, string userAccessToken)
        {
            var address = string.Format(FriendsUrl, userId, friendId);
            var param = string.Format("access_token={0}", userAccessToken);

            var client = new WebClient();
            client.Encoding = Encoding.UTF8;
            client.Headers["content-type"] = "application/x-www-form-urlencoded";

            var response = client.UploadString(address, "POST", param);

            return response == "true";
        }

        public dynamic Query(string fql, string userAccessToken)
        {

            var address = string.Format("https://api.facebook.com/method/fql.query?query={0}&access_token={1}&format=JSON",
                HttpUtility.UrlEncode(fql),
                userAccessToken);
            var client = new WebClient();
            var response = client.DownloadString(address);

            return SimpleJson.SimpleJson.DeserializeObject(response);
        }

        public dynamic Get(string api, string userAccessToken)
        {
            var address = string.Format("https://graph.facebook.com/{0}{1}access_token={2}",
                api,
                api.Contains("?") ? "&" : "?",
                userAccessToken);

            var client = new WebClient();
            var response = client.DownloadString(address);

            return SimpleJson.SimpleJson.DeserializeObject(response);

        }

    }

    public enum UserPermissions
    {
        user_about_me,
        user_activities,
        user_birthday,
        user_education_history,
        user_events,
        user_groups,
        user_hometown,
        user_interests,
        user_likes,
        user_location,
        user_notes,
        user_online_presence,
        user_photo_video_tags,
        user_photos,
        user_relationships,
        user_relationship_details,
        user_religion_politics,
        user_status,
        user_videos,
        user_website,
        user_work_history,
        email,
        read_friendlists,
        read_insights,
        read_mailbox,
        read_requests,
        read_stream,
        xmpp_login,
        ads_management,
        user_checkins
    }

    public enum FriendPermissions
    {
        friends_about_me,
        friends_activities,
        friends_birthday,
        friends_education_history,
        friends_events,
        friends_groups,
        friends_hometown,
        friends_interests,
        friends_likes,
        friends_location,
        friends_notes,
        friends_online_presence,
        friends_photo_video_tags,
        friends_photos,
        friends_relationships,
        friends_relationship_details,
        friends_religion_politics,
        friends_status,
        friends_videos,
        friends_website,
        friends_work_history,
        manage_friendlists,
        friends_checkins
    }

    public class TestUser
    {
        public string id { get; set; }
        public string access_token { get; set; }
        public string login_url { get; set; }

        public string idAndToken { get { return string.Format("{0},{1}", id, access_token); } }
        public bool isFriend { set; get; }
        public bool isNotFriend { get { return !isFriend; } }
    }
}
